/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.configuration.event; import java.util.LinkedList; import org.apache.commons.configuration.AbstractConfiguration; import org.apache.commons.configuration.event.ConfigurationEvent; import org.apache.commons.configuration.event.ConfigurationListener; import junit.framework.TestCase; /** * Base class for testing events generated by configuration classes derived from * AbstractConfiguration. This class implements a couple of tests related to * event generation. Concrete sub classes only have to implement the * <code>createConfiguration()</code> method for creating an instance of a * specific configuration class. Because tests for detail events depend on a * concrete implementation an exact sequence of events cannot be checked. * Instead the corresponding test methods check whether the enclosing events * (not the detail events) are of the expected type. * * @version $Id: AbstractTestConfigurationEvents.java 531254 2007-04-22 18:54:57Z oheger $ */ public abstract class AbstractTestConfigurationEvents extends TestCase { /** Constant for a test property name. */ static final String TEST_PROPNAME = "event.test"; /** Constant for a test property value. */ static final String TEST_PROPVALUE = "a value"; /** Constant for an existing property. */ static final String EXIST_PROPERTY = "event.property"; /** The configuration to be tested. */ protected AbstractConfiguration config; /** A test event listener. */ protected TestConfigurationListener l; protected void setUp() throws Exception { super.setUp(); config = createConfiguration(); config.addProperty(EXIST_PROPERTY, "existing value"); l = new TestConfigurationListener(); config.addConfigurationListener(l); } /** * Creates the configuration instance to be tested. * * @return the configuration instance under test */ protected abstract AbstractConfiguration createConfiguration(); /** * Tests events generated by addProperty(). */ public void testAddPropertyEvent() { config.addProperty(TEST_PROPNAME, TEST_PROPVALUE); l.checkEvent(AbstractConfiguration.EVENT_ADD_PROPERTY, TEST_PROPNAME, TEST_PROPVALUE, true); l.checkEvent(AbstractConfiguration.EVENT_ADD_PROPERTY, TEST_PROPNAME, TEST_PROPVALUE, false); l.done(); } /** * Tests events generated by addProperty() when detail events are enabled. */ public void testAddPropertyEventWithDetails() { config.setDetailEvents(true); config.addProperty(TEST_PROPNAME, TEST_PROPVALUE); l.checkEventCount(2); l.checkEvent(AbstractConfiguration.EVENT_ADD_PROPERTY, TEST_PROPNAME, TEST_PROPVALUE, true); l.skipToLast(AbstractConfiguration.EVENT_ADD_PROPERTY); l.checkEvent(AbstractConfiguration.EVENT_ADD_PROPERTY, TEST_PROPNAME, TEST_PROPVALUE, false); l.done(); } /** * Tests events generated by clearProperty(). */ public void testClearPropertyEvent() { config.clearProperty(EXIST_PROPERTY); l.checkEvent(AbstractConfiguration.EVENT_CLEAR_PROPERTY, EXIST_PROPERTY, null, true); l.checkEvent(AbstractConfiguration.EVENT_CLEAR_PROPERTY, EXIST_PROPERTY, null, false); l.done(); } /** * Tests events generated by clearProperty() when detail events are enabled. */ public void testClearPropertyEventWithDetails() { config.setDetailEvents(true); config.clearProperty(EXIST_PROPERTY); l.checkEventCount(2); l.checkEvent(AbstractConfiguration.EVENT_CLEAR_PROPERTY, EXIST_PROPERTY, null, true); l.skipToLast(AbstractConfiguration.EVENT_CLEAR_PROPERTY); l.checkEvent(AbstractConfiguration.EVENT_CLEAR_PROPERTY, EXIST_PROPERTY, null, false); l.done(); } /** * Tests events generated by setProperty(). */ public void testSetPropertyEvent() { config.setProperty(EXIST_PROPERTY, TEST_PROPVALUE); l.checkEvent(AbstractConfiguration.EVENT_SET_PROPERTY, EXIST_PROPERTY, TEST_PROPVALUE, true); l.checkEvent(AbstractConfiguration.EVENT_SET_PROPERTY, EXIST_PROPERTY, TEST_PROPVALUE, false); l.done(); } /** * Tests events generated by setProperty() when detail events are enabled. */ public void testSetPropertyEventWithDetails() { config.setDetailEvents(true); config.setProperty(EXIST_PROPERTY, TEST_PROPVALUE); l.checkEventCount(2); l.checkEvent(AbstractConfiguration.EVENT_SET_PROPERTY, EXIST_PROPERTY, TEST_PROPVALUE, true); l.skipToLast(AbstractConfiguration.EVENT_SET_PROPERTY); l.checkEvent(AbstractConfiguration.EVENT_SET_PROPERTY, EXIST_PROPERTY, TEST_PROPVALUE, false); l.done(); } /** * Tests the events generated by the clear() method. */ public void testClearEvent() { config.clear(); l.checkEvent(AbstractConfiguration.EVENT_CLEAR, null, null, true); l.checkEvent(AbstractConfiguration.EVENT_CLEAR, null, null, false); l.done(); } /** * Tests the events generated by the clear method when detail events are * enabled. */ public void testClearEventWithDetails() { config.setDetailEvents(true); config.clear(); l.checkEventCount(2); l.checkEvent(AbstractConfiguration.EVENT_CLEAR, null, null, true); l.skipToLast(AbstractConfiguration.EVENT_CLEAR); l.checkEvent(AbstractConfiguration.EVENT_CLEAR, null, null, false); l.done(); } /** * A test event listener class used for testing events generated by the * configuration. */ protected class TestConfigurationListener implements ConfigurationListener { /** Stores the received events. */ private LinkedList events = new LinkedList(); public void configurationChanged(ConfigurationEvent event) { events.add(event); } /** * Checks if at least <code>minEvents</code> events have been * received. * * @param minEvents the minimum number of expected events */ public void checkEventCount(int minEvents) { assertTrue("Too view events received", events.size() >= minEvents); } /** * Checks an expected event. * * @param type the event type * @param propName the expected property name * @param propValue the expected property value * @param before the expected before flag */ public void checkEvent(int type, String propName, Object propValue, boolean before) { ConfigurationEvent e = nextEvent(type); assertEquals("Wrong property name", propName, e.getPropertyName()); assertEquals("Wrong property value", propValue, e .getPropertyValue()); assertEquals("Wrong before flag", before, e.isBeforeUpdate()); } /** * Returns the next received event and checks for the expected type. * This method can be used instead of <code>checkEvent()</code> for * comparing complex event values. * @param expectedType the expected type of the event * @return the event object */ public ConfigurationEvent nextEvent(int expectedType) { assertFalse("Too few events received", events.isEmpty()); ConfigurationEvent e = (ConfigurationEvent) events.removeFirst(); assertEquals("Wrong event source", config, e.getSource()); assertEquals("Wrong event type", expectedType, e.getType()); return e; } /** * Skips to the last received event and checks that no events of the * given type have been received. This method is used by checks for * detail events to ignore the detail events. * * @param type the event type */ public void skipToLast(int type) { while (events.size() > 1) { ConfigurationEvent e = (ConfigurationEvent) events .removeFirst(); assertTrue("Found end event in details", type != e.getType()); } } /** * Checks if all events has been processed. */ public void done() { assertTrue("Too many events received", events.isEmpty()); } } }